<?php
/**
* @version 1.0
* @since June-2008
* @name CStructureID
* @deprecated Tap hop cac ham thao tac voi cac bang co ID co cau truc cay
*
*@since 18/4/2005
*/
class CStructureID
{
	/**
	 * Số bản ghi tối đa ở cùng một cấp thuộc một gốc
	 *
	 */
	const ID_BASE = 100.0;
	/**
	 * Số level tối đa
	 *
	 */
	const ID_MAX_LEVEL = 9;
	/**
	 * ID gốc
	 *
	 */
	const ID_ROOT = "1000000000000000000";
	/**
	 * Structure ID
	 *
	 * @var int
	 */
	public $structure_id = CStructureID::ID_ROOT;
	/**
	 * Khởi tạo
	 *
	 * @param int $structure_id
	 */
	function __construct($structure_id)
	{
		$this->structure_id = number_format($structure_id,0,'','');
	}
	/**
	 * Kiểm tra xem trong bảng $table đối tượng hiện tại có node con hay không
	 * @param string $table Tên bảng cần kiểm tra
	 * @return bool
	 */
	function have_child($table)
	{
		return CTable($table)->select($this->child_condition());
	}
	/**
	 * Lấy structure id cha của structure id hiện tại
	 *
	 * @return int
	 */
 	function parent()
	{
		if($this->structure_id == CStructureID::ID_ROOT)
		{
			return false;
		}
		else
		{
			$level = $this->level();
			$structure_id = number_format($this->structure_id,0,'','').'';
			if($level!=0)
			{
				$structure_id{$level*2-1}='0';
				$structure_id{$level*2}='0';
			}
			return number_format($structure_id,0,'','');
		}
	}
	
	/**
	 * Lấy structure id tiếp theo
	 *
	 * @return int
	 */
	function next()
	{
		return number_format($this->structure_id+pow(CStructureID::ID_BASE,CStructureID::ID_MAX_LEVEL - $this->level()),0,'','');
	}
	/**
	 * Kiểm tra xem $parent_id có phải là cha của structure id này không
	 *
	 * @param int $parent_id
	 * @return bool 
	 */
	function is_child($parent_id)
	{	
		return $this->structure_id > $parent_id and $this->structure_id < CStructureID($parent_id)->next();
	}
	/**
	 * Trả về biểu thức điều kiện dạng CExpression để lấy ra các node cha của structure id này
	 *
	 * @return CExpression
	 */
	function path_condition()
	{
		$structure_id = $this->structure_id;
		$expr = new CExpression('IN','structure_id',$structure_id);
		while($structure_id = CStructureID($structure_id)->parent())
		{
			$expr->factors[] = $structure_id;
		}
		return $expr;
	}
	/**
	 * Trả về biểu thức điều kiện dạng CExpression để lấy ra các node con của structure id này
	 *
	 * @param bool $except_me Có lấy cả node hiện tại không
	 * @return CExpression
	 */
	function child_condition($except_me = false)
	{	
		if($except_me)
		{
			return EAnd(EGT('structure_id', $this->structure_id), ELT('structure_id', $this->next()));
		}
		else
		{
			return EAnd(EGTE('structure_id', $this->structure_id), ELT('structure_id', $this->next()));
		}
	}
	/**
	 * Trả về biểu thức điều kiện dạng CExpression để lấy ra các node phía trên của structure_id này
	 *
	 * @param bool $except_me Có lấy cả node hiện tại không
	 * @return CExpression
	 */
	function above_condition($except_me = false)
	{	
		$parent_si = $this-> parent();
		if($except_me)
		{
			return EAnd(EGT('structure_id', CStructureID($parent_si)->first_child()), ELT('structure_id', $this->structure_id));
		}
		else
		{
			return EAnd(EGTE('structure_id', CStructureID($parent_si)->first_child()), ELT('structure_id', $this->structure_id));
		}
	}
	/**
	 * Trả về biểu thức điều kiện dạng CExpression để lấy ra các node con trực tiếp của structure id này
	 *
	 * @param int $child_level lấy đến mức nào
	 * @return CExpression
	 */
	function direct_child_condition($child_level=1)
	{	
		$level = $this->level();
		$child_offset = number_format(pow(CStructureID::ID_BASE, CStructureID::ID_MAX_LEVEL-($level+$child_level)),0,'','');
		return EAnd($this->child_cond(true), EEqual(EMod('structure_id', $child_offset),0));
	}
	
 /**
 * Hàm tính ra structure_id nút cùng cấp tiếp theo của một nút
 *
 * @return structure_id nút cùng cấp tiếp theo của một nút.
 */
	 function next_structure_id()
	{	
		return inc($this->structure_id);		
	}	
 
	public function level()
	{
		$st=''.$this -> structure_id.'000';		
		return intval(strpos($st,'000')/2);
	}
/**
 * Hàm trả về  structure_id con đầu tiên của một node
 */
	function first_child()
	{ 			
		$fc	=prefix($this -> structure_id) . '01';
		$fc = $fc . '000000000000000000';
		$fc=substr($fc,0,1+ CStructureID::ID_MAX_LEVEL *2);			
		return floatval($fc * 1.0);
	}
	
/**
 * Hàm lấy ra Structure_id phía trên k bậc
 *
 * @return 
 */
	function above_structure_id($k=1)
	{ 			
		return dec($this->structure_id,$k);		
	}
/**
 * Hàm lấy ra Structure_id phía dưới k bậc
 *
 * @return 
 */	
	function under_structure_id($k=1)
	{ 			
		return inc($this->structure_id,$k);
	}
} //end class
	
/**
/**
 * Tạo một đối tượng CStructureID
 *
 * @param int $structure_id
 * @return CStructureID
 */
function  CStructureID($structure_id) 
{
	return new CStructureID($structure_id);
}
/**
 * Hàm lấy ra đọan đầu các số khác không của một Structure_id;
 *
 * @return Đoạn các số khác không.
 */	
function prefix($structure_id)
	{ 	
		$pre =strval(CNumber($structure_id)->number());		
		$pre =substr($pre,0,strpos($pre,'000'));
		if (strlen($pre)%2 == 0)
		{
			$pre=$pre . '0'	;
		}
		;
		return CNumber($pre * 1.0)->number();	
	}
/**
 * Tang Structure_id len mot
 *
 * @param int $structure_id structure_id can tang
 * @return unknown
 */

	function inc($structure_id, $k=1)
	{ 			
		$temp = substr(prefix($structure_id),0,strlen(prefix($structure_id))-2);
		$temp2 = substr(prefix($structure_id),-2);
		$temp2 = intval(intval($temp2) + $k);	
		if ($temp2 <= 9 )
		{
			
			$temp2= '0'.$temp2;
		}
		$temp = $temp.$temp2;
		$temp = $temp . '000000000000000000';
		$temp=substr($temp,0,1+ CStructureID::ID_MAX_LEVEL *2);		
		return CNumber($temp)->number();
	}
	function dec($structure_id, $k=1)
	{ 			
		$temp = substr(prefix($structure_id),0,strlen(prefix($structure_id))-2);
		$temp2 = substr(prefix($structure_id),-2);
		$temp2 = intval(intval($temp2) - $k);	
		if ($temp2 <= 9 )
		{
			
			$temp2= '0'.$temp2;
		}
		$temp = $temp.$temp2;
		$temp = $temp . '000000000000000000';
		$temp=substr($temp,0,1+ CStructureID::ID_MAX_LEVEL *2);		
		return CNumber($temp)->number();
	}		
	
?>